oo::class create PopupInfoVarsDialog {
    superclass PopupDialog
    variable Path PopUpFlag OKVal CancelVal ifDestroy \
        InfoVars ThreadError ThreadResult ThreadStdout \
        ItemList

    constructor {args} {
        next {*}$args
        set InfoVars {}
        set ThreadStdout {}
        set ThreadResult {}
        set ThreadError {}
        set ItemList {}
    }

    method popup {msg infovars err ret out} {
        my setInfo $infovars $err $ret $out
        set ItemList {}

        next $msg
    }

    method setInfo {infovars err ret out} {
        set InfoVars $infovars
        set ThreadStdout $out
        set ThreadResult $ret
        set ThreadError $err
    }

    method createPopup {msg} {
        next $msg
        ttk::frame $Path.bottom
        ttk::sizegrip $Path.bottom.sg
        pack $Path.bottom.sg -side right
        pack forget $Path.btns
        pack $Path.bottom -side bottom -fill x
        pack $Path.btns -side bottom -fill x
        wm resizable $Path 1 1

        set frame [frame $Path.infovars]
        ttk::notebook $frame.nb -width 350 -height 250
        $frame.nb insert end [frame $frame.nb.vars] -text vars
        my createVarTree $frame.nb.vars

        $frame.nb insert end [frame $frame.nb.result] -text result
        pack [text $frame.nb.result.txt] -fill both -expand 1
        $frame.nb.result.txt insert end $ThreadResult
        $frame.nb.result.txt configure -state disable

        $frame.nb insert end [frame $frame.nb.error] -text stderr
        pack [text $frame.nb.error.txt] -fill both -expand 1
        $frame.nb.error.txt insert end $ThreadError
        $frame.nb.error.txt configure -state disable

        $frame.nb insert end [frame $frame.nb.stdout] -text stdout
        pack [text $frame.nb.stdout.txt] -fill both -expand 1
        $frame.nb.stdout.txt insert end $ThreadStdout
        $frame.nb.stdout.txt configure -state disable

        pack $frame.nb -fill both -expand 1
        pack $frame -side top -fill both -expand 1

        $Path.btns.ok configure -text Continue -command [list [self object] continueAndUpdateinfo]
        bind $Path.btns.ok <Return> [list [self object] continueAndUpdateinfo]

        set debugMenuObj [lindex [info class instances ::DebugMenu] 0]
        set debugMenuObjNamespace [info object namespace $debugMenuObj]
        if {[set ${debugMenuObjNamespace}::Thread] == {}} {
            $Path.btns.ok configure -state disable
        }
    }

    method continueAndUpdateinfo {} {
        set debugMenuObj [lindex [info class instances ::DebugMenu] 0]
        set debugMenuObjNamespace [info object namespace $debugMenuObj]
        $debugMenuObj continueDebug
        $debugMenuObj setThreadInfo
        my setInfo [set ${debugMenuObjNamespace}::InfoVars] \
            [set ${debugMenuObjNamespace}::ThreadError] \
            [set ${debugMenuObjNamespace}::ThreadResult] \
            [set ${debugMenuObjNamespace}::ThreadStdout]
        my displayInfoVars [lindex [lindex $InfoVars 0] 0]
        $Path.infovars.nb.result.txt delete 1.0 end
        $Path.infovars.nb.result.txt insert 1.0 $ThreadResult
        $Path.infovars.nb.stdout.txt delete 1.0 end
        $Path.infovars.nb.stdout.txt insert 1.0 $ThreadStdout
        $Path.infovars.nb.error.txt delete 1.0 end
        $Path.infovars.nb.error.txt insert 1.0 $ThreadError

        after idle [subst {
            if {\[set ${debugMenuObjNamespace}::Thread\] == {}} {
                $Path.btns.ok configure -state disable
            }
        }]
    }

    method createVarTree {parent} {
        frame $parent.f
        ttk::label $parent.f.level -text [lindex [lindex $InfoVars 0] 0] -width 3 -anchor center
        ttk::button $parent.f.btn1 -text Up -command [list [self object] displayUplevelInfoVars]
        ttk::button $parent.f.btn2 -text Low -command [list [self object] displayLowlevelInfoVars]

        pack $parent.f.btn2 $parent.f.level $parent.f.btn1 -side left -padx 1
        pack $parent.f -side top -pady 3

        ttk::treeview $parent.tree -column {variable value} -show headings \
            -yscroll "$parent.vsb set" -xscroll "$parent.hsb set"
        $parent.tree heading variable -text Variable
        $parent.tree heading value -text Value
        $parent.tree column variable -width 10
        $parent.tree column value -width 20
        my displayInfoVars [lindex [lindex $InfoVars 0] 0]

        ttk::scrollbar $parent.vsb -orient vertical -command "$parent.tree yview"
        ttk::scrollbar $parent.hsb -orient horizontal -command "$parent.tree xview"
        pack $parent.hsb -side bottom -fill x
        pack $parent.vsb -side right -fill y
        pack $parent.tree -fill both -expand 1
    }

    method displayLowlevelInfoVars {}  {
        set level [$Path.infovars.nb.vars.f.level cget -text]
        if {$level != {}} {
            my displayInfoVars [expr $level+1]
        }
    }

    method displayUplevelInfoVars {}  {
        set level [$Path.infovars.nb.vars.f.level cget -text]
        if {$level != {}} {
            my displayInfoVars [expr $level-1]
        }
    }

    method displayInfoVars {level} {
        foreach row $InfoVars {
            foreach {l data} $row {
                if {$l == $level} {
                    foreach item $ItemList {
                        $Path.infovars.nb.vars.tree delete $item
                    }
                    set ItemList {}
                    $Path.infovars.nb.vars.f.level configure -text $l
                    foreach item $data {
                        lappend ItemList [$Path.infovars.nb.vars.tree insert {} end -values $item]
                    }
                    break
                }
            }
        }
    }
}